package com.atzly.community.controller;

import com.atzly.community.constant.CommentConstant;
import com.atzly.community.entity.*;
import com.atzly.community.event.EventProducter;
import com.atzly.community.service.*;
import com.atzly.community.utils.CommunityUtils;
import com.atzly.community.utils.HostHolder;
import com.atzly.community.utils.RedisKeyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 发帖
 *
 * @author zlysimida
 * @date 2021/8/25 - 12:01
 */
@Controller
public class DiscussPostController implements CommentConstant {

    @Autowired
    private DiscussPostService discussPostService;

    @Autowired
    private UserService userService;

    @Autowired
    private HostHolder hostHolder;

    @Autowired
    private CommentService commentService;

    @Autowired
    private LikeService likeService;

    @Autowired
    private EventProducter eventProducter;

    @Autowired
    private RedisTemplate redisTemplate;

    @GetMapping("/")
    public String root() {
        return "forward:/index";
    }

    // 从数据库中建立页面page,从redis的set点赞集合中统计帖子的个数
    @GetMapping(path =  {"/index"})
    public String getDiscussPost(Model model, Page page, @RequestParam(value = "orderMode", defaultValue = "0") int orderMode) {
        // 在SpringMVC中函数参数在返回时,被封装到model中
        page.setTotal(discussPostService.selectDiscussByUserId(0));
        page.setPath("/index?orderMode=" + orderMode);
        List<DiscussPost> discussPosts = discussPostService.selectDiscussPost(0, page.getOffset(), page.getLimit(), orderMode);
        List<Map<String, Object>> returnValues = new ArrayList<>();
        if (discussPosts != null) {
            for (DiscussPost post : discussPosts) {
                Map<String, Object> map = new HashMap<>();
                map.put("post", post);
                User user = userService.selectById(post.getUserId());
                map.put("user", user);
                // 查找帖子的赞
                long likeCount = likeService.findEntityLikeCount(CommentConstant.ENTITY_TYPE_POST, post.getId());
                map.put("likeCount", likeCount);
                returnValues.add(map);
            }
        }
        model.addAttribute("data", returnValues);
        model.addAttribute("orderMode", orderMode);
        return "/index";
    }

    // 异步发帖
    // 发帖过程: 首先向数据库中添加当前帖子,然后使用kafaka将当前帖子异步添加到es中,最后将帖子id保存到redis的set中
    @PostMapping("/discuss/add")
    @ResponseBody
    public String addDiscussPost(String title, String content) {
        User user = hostHolder.getUserFromThread();
        if (user == null) {
            return CommunityUtils.JsontoString(403, "您还没有登录哦!");
        }

        DiscussPost post = new DiscussPost();
        post.setUserId(user.getId());
        post.setTitle(title);
        post.setContent(content);
        post.setCreateTime(new Date());
        // 保存帖子到数据库并转义处理
        discussPostService.insertDiscussPostAndPrase(post);

        // 发帖成功触发事件添加到es
        Event event = new Event()
                .setTopic(TOPIC_PUBLISH)
                .setUserId(user.getId())
                .setEntityType(ENTITY_TYPE_POST)
                .setEntityId(post.getId());
        eventProducter.sendMessage(event);

        // 记录下当前需要刷新的帖子保存到redis中
        String redisKey = RedisKeyUtils.getPostScoreKey();
        redisTemplate.opsForSet().add(redisKey, post.getId());

        // 报错的情况统一处理
        return CommunityUtils.JsontoString(0, "发布成功!");
    }

    // 帖子详情: 首先从数据库中查询帖子,然后从数据库中查询帖子作者，然后根据当前帖子类型以及帖子id在redis中查询点赞的数量（set），然后根据帖子类型以及帖子id以及作者id从redis中获取用户对该帖子是否点赞，
    // 然后查询评论分页信息包括对主帖的评论，以及对评论的评论（主要获取到当前帖子下每一条评论，然后再获取每一条评论的全部回复）然后获取评论数量并返回当前评论列表
    @GetMapping("/discuss/show/{discussId}")
    public String showDiscussPostDetial(@PathVariable("discussId") int discussId,
                                        Model model,
                                        Page page) {
        // 查询帖子
        DiscussPost post = discussPostService.selectDiscussDetails(discussId);
        // 查询作者
        User user = userService.selectById(post.getUserId());
        model.addAttribute("post", post);
        model.addAttribute("user", user);

        // 点赞数量
        long likeCount = likeService.findEntityLikeCount(CommentConstant.ENTITY_TYPE_POST, discussId);
        model.addAttribute("likeCount", likeCount);
        // 点赞状态
        int likeStatus = user == null ? 0 : likeService.findEntityLikeStatus(user.getId(), CommentConstant.ENTITY_TYPE_POST, discussId);
        model.addAttribute("likeStatus", likeStatus);


        // 查询评论分页信息
        // 评论  给帖子的评论 1
        // 回复  给评论的评论 2
        page.setLimit(5);
        page.setPath("/discuss/show/" + discussId);
        page.setTotal(post.getCommentCount());
        // 评论列表
        List<Comment> commentList = commentService.getCommentAndPage(
                CommentConstant.ENTITY_TYPE_POST, discussId, page.getOffset(), page.getLimit());

        List<Map<String, Object>> commentVoList = new ArrayList<>();
        if (commentList != null) {
            for (Comment comment : commentList) {
                // 获取到每条评论
                Map<String, Object> commentVo = new HashMap<>();
                commentVo.put("comment", comment);
                commentVo.put("user", userService.selectById(comment.getUserId()));
                // 点赞数量
                likeCount = likeService.findEntityLikeCount(CommentConstant.ENTITY_TYPE_COMMENT, comment.getId());
                commentVo.put("likeCount", likeCount);
                // 点赞状态
                likeStatus = user == null ? 0 : likeService.findEntityLikeStatus(user.getId(), CommentConstant.ENTITY_TYPE_COMMENT, comment.getId());
                commentVo.put("likeStatus", likeStatus);
                // 获取每条评论的全部回复
                List<Comment> replyList = commentService.getCommentAndPage(
                        CommentConstant.ENTITY_TYPE_COMMENT, comment.getId(), 0, Integer.MAX_VALUE);
                List<Map<String, Object>> replyVoList = new ArrayList<>();
                if (replyList != null) {
                    for (Comment reply : replyList) {
                        Map<String, Object> replyVo = new HashMap<>();
                        replyVo.put("reply", reply);
                        replyVo.put("user", userService.selectById(reply.getUserId()));
                        // 回复目标
                        User target = reply.getTargetId() == 0 ? null : userService.selectById(reply.getTargetId());
                        replyVo.put("target", target);

                        // 点赞
                        likeCount = likeService.findEntityLikeCount(CommentConstant.ENTITY_TYPE_COMMENT, reply.getId());
                        replyVo.put("likeCount", likeCount);
                        // 点赞状态
                        likeStatus = user == null ? 0 : likeService.findEntityLikeStatus(user.getId(), CommentConstant.ENTITY_TYPE_COMMENT, reply.getId());
                        replyVo.put("likeStatus", likeStatus);

                        replyVoList.add(replyVo);
                    }
                }
                commentVo.put("replys", replyVoList);
                // 回复的数量
                int replyCount = commentService.getComment(CommentConstant.ENTITY_TYPE_COMMENT, comment.getId());
                commentVo.put("replyCount", replyCount);
                // 将评论的所有详细信息保存到列表中返回
                commentVoList.add(commentVo);
            }
        }
        model.addAttribute("comments", commentVoList);
        return "/site/discuss-detail";
    }

    // 帖子置顶: 首先更新数据库帖子的类型，然后使用kafaka将当前帖子异步（延迟）更新到es中
    @PostMapping("/discuss/top")
    @ResponseBody
    public String postTop(int postId) {
        discussPostService.updateDiscussPostType(postId, 1);

        // 更新es中的数据
        // 更新成功触发事件
        Event event = new Event()
                .setTopic(TOPIC_PUBLISH)
                .setUserId(hostHolder.getUserFromThread().getId())
                .setEntityType(ENTITY_TYPE_POST)
                .setEntityId(postId);
        eventProducter.sendMessage(event);

        return CommunityUtils.JsontoString(0, "置顶成功!");
    }

    // 帖子加精: 首先更新数据库帖子的状态为1,  然后使用kafaka将当前帖子异步（延迟）更新到es中
    @PostMapping("/discuss/digest")
    @ResponseBody
    public String addToDigest(int postId) {
        discussPostService.updateDiscussPostStatus(postId, 1);

        // 更新es中的数据
        // 更新成功触发事件
        Event event = new Event()
                .setTopic(TOPIC_PUBLISH)
                .setUserId(hostHolder.getUserFromThread().getId())
                .setEntityType(ENTITY_TYPE_POST)
                .setEntityId(postId);
        eventProducter.sendMessage(event);
        // 记录下需要刷新的帖子
        String redisKey = RedisKeyUtils.getPostScoreKey();
        redisTemplate.opsForSet().add(redisKey, postId);

        return CommunityUtils.JsontoString(0, "加精成功");
    }

    // 帖子删除: 首先更新数据库帖子的状态为3, 然后使用kafaka将当前帖子异步（延迟）从es中删除
    @PostMapping("/discuss/delete")
    @ResponseBody
    public String postDelete(int postId) {
        discussPostService.updateDiscussPostStatus(postId, 2);
        // 更新es中的数据
        // 更新成功触发事件
        Event event = new Event()
                .setTopic(TOPIC_DELETE)
                .setUserId(hostHolder.getUserFromThread().getId())
                .setEntityType(ENTITY_TYPE_POST)
                .setEntityId(postId);
        eventProducter.sendMessage(event);

        return CommunityUtils.JsontoString(0, "删除成功");
    }
}
